package br.com.chat.views;

import java.util.List;

import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import br.com.chat.ChatController;
import br.com.chat.ChatUpdatable;
import br.com.chat.Message;
import br.com.chat.MessageReceiver;
import br.com.chat.User;


/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

public class ChatView extends ViewPart implements ChatUpdatable {
    
    private ChatController controller = new ChatController( this );
    
    private Button btnLogin;
    private Button btnLogout;
    private Button btnclearMessage;
    private Button btnScrollLock;
    
    private Text txtMessage;
    private Text txtHistory;
    
    private Label lblLog;
    
    private boolean scrollLocked;
    
    /**
     * The ID of the view as specified by the extension.
     */
    public static final String ID = "br.com.chat.views.ChatView";

    @Override
    public void createPartControl(final Composite parent) {
        GridLayout layout = new GridLayout();
        layout.numColumns = 5;
        parent.setLayout(layout);
        
        GridData gridData;
        
        btnLogin = new Button(parent, SWT.PUSH);
        btnLogin.setText("Entrar");
        btnLogin.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                getSite().getShell().getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        InputDialog dialog = new InputDialog(getSite().getShell(), "Joke Chat", "Informe o seu nick", "", null);
                        
                        dialog.open();
                        
                        String username = dialog.getValue();
                        
                        if ( username == null || username.isEmpty() ){
                            return;
                        }
                        
                        controller.setUser(new User(username));
                        
                        if ( controller.login() ){
                            Thread thread = new Thread(new MessageReceiver(controller, ChatView.this));
                            thread.setPriority(Thread.MIN_PRIORITY);
                            thread.start();
                        }
                    }
                });
            }
        });
        
        btnLogout = new Button(parent, SWT.PUSH);
        btnLogout.setText("Sair");
        btnLogout.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                controller.logout();
            }
        });
        
        
        btnclearMessage = new Button(parent, SWT.PUSH);
        btnclearMessage.setText("Limpa mensagens");
        btnclearMessage.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Display.getDefault().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if ( !txtHistory.isDisposed() && txtHistory != null ){
                            txtHistory.setText("");
                        }
                    }
                });
            }
        });
        
        btnScrollLock = new Button(parent, SWT.CHECK);
        btnScrollLock.setText("Travar scroll");
        btnScrollLock.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Display.getDefault().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        scrollLocked = !scrollLocked;
                        
                        System.out.println( ">>>>>>>>>>>" + scrollLocked );
                    }
                });
            }
        });
        
        gridData = new GridData(GridData.FILL, GridData.CENTER, true, false);
        
        lblLog = new Label(parent, SWT.NONE);
        lblLog.setLayoutData(gridData);
        
        gridData = new GridData(GridData.FILL, GridData.CENTER, true, false);
        gridData.horizontalSpan = 5;
        
        txtMessage = new Text(parent, SWT.SINGLE | SWT.BORDER );
        txtMessage.setLayoutData(gridData);
        txtMessage.addTraverseListener(new TraverseListener() {
            @Override
            public void keyTraversed(TraverseEvent event) {
                if ( event.detail == SWT.TRAVERSE_RETURN){
                    sendMessage(txtMessage);
                }
            }
        });
        
        gridData = new GridData();
        gridData.verticalAlignment = GridData.FILL;
        gridData.grabExcessVerticalSpace = true;
        gridData.horizontalAlignment = GridData.FILL;
        gridData.horizontalSpan = 5;
        gridData.grabExcessHorizontalSpace= true;
        
        txtHistory = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL );
        txtHistory.setLayoutData(gridData);
    }

    @Override
    public void setFocus() {

    }
    
    @Override
    public void log(final String content) {
        Display.getDefault().asyncExec(new Runnable() {
            @Override
            public void run() {
                if ( !lblLog.isDisposed() && lblLog != null ){
                    lblLog.setText(content);
                }
            }
        });
    }
    
    @Override
    public void updateChat(final List<Message> messages) {
        try {
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    if (!txtHistory.isDisposed() && txtHistory != null) {
                        CharSequence content = controller.updateHistory(messages);
                        content = content + txtHistory.getText();
                        
                        if ( !scrollLocked ){
                            txtHistory.setText(content.toString());
                        }
                        else{
                            txtHistory.setRedraw(false);
                            int scrollP = txtHistory.getTopIndex();
                            Point selectionP = txtHistory.getSelection();              
                            txtHistory.setText(content.toString());
                            txtHistory.setSelection(selectionP);
                            txtHistory.setTopIndex(scrollP);
                            txtHistory.setRedraw(true);
                        }
                    }
                }
            });
        } catch (SWTException e) {
            // eat it!
        }
    }
    
    private void sendMessage(final Text component) {
        try {
            controller.sendMessage(component.getText());
            component.setText("");
        } catch (Exception e) {
            lblLog.setText(e.getMessage());
        }
    }
}